package com.szeldon.declatest.eval.plugins;

import java.util.Date;
import java.util.Properties;

import org.testng.Assert;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;

import com.szeldon.declatest.eval.exceptions.EvaluationException;
import com.szeldon.declatest.exec.TestSuiteExecHistory;
import com.szeldon.declatest.exec.events.dostep.jms.JmsMessageReceivedExecEvent;

/**
 * Unit tests for {@link DefaultEvaluatorPlugin} class.
 * 
 * @author szeldon
 * 
 */
public class DefaultEvaluatorPluginTest {

    private DefaultEvaluatorPlugin plugin;

    @BeforeTest
    public void beforeTest() {
        plugin = new DefaultEvaluatorPlugin();
    }

    @Test(expectedExceptions = EvaluationException.class)
    public void testEvaluateNotProperValueNotClosedExpression() throws EvaluationException {
        String evaluated = plugin.evaluateValue(null, "${something", null, null);
    }

    @Test
    public void testEvaluateNotProperValueWithPropertyExpression() throws EvaluationException {
        Properties properties = new Properties();
        properties.put("some", "some-value");
        String evaluated = plugin.evaluateValue(null, "${some@property}", properties, null);
        Assert.assertEquals(evaluated, null);
    }

    @Test
    public void testEvaluateProperPropertyValue() throws EvaluationException {
        Properties properties = new Properties();
        properties.put("something", "some-value");
        String evaluated = plugin.evaluateValue(null, "something@property", properties, null);
        Assert.assertEquals(evaluated, "some-value");

    }

    @Test
    public void testEvaluateProperStepResponseValue() throws EvaluationException {
        TestSuiteExecHistory history = new TestSuiteExecHistory("test-suite-id");
        history.addExecEvent(new JmsMessageReceivedExecEvent("scenarioId", "event description", new Date(),
                "scenarioStepId", "stepDescription", "stepEndpointId", "stepRequestPath", "endpointDescription",
                "endpointUrl", "endpointSettingsId", "queue", "queueName", "responseContent"));
        String evaluated = plugin.evaluateValue(null, "response@scenarioStepId@step", null, history);
        Assert.assertEquals(evaluated, "responseContent");
    }

    @Test(expectedExceptions = EvaluationException.class)
    public void testEvaluateProperStepNoResponseValue() throws EvaluationException {
        TestSuiteExecHistory history = new TestSuiteExecHistory("test-suite-id");
        history.addExecEvent(new JmsMessageReceivedExecEvent("scenarioId", "event description", new Date(),
                "scenarioStepId", "stepDescription", "stepEndpointId", "stepRequestPath", "endpointDescription",
                "endpointUrl", "endpointSettingsId", "queue", "queueName", "responseContent"));
        String evaluated = plugin.evaluateValue(null, "response@badScenarioStepId@step", null, history);
    }

    @Test
    public void testEvaluateUnixTimeDateFunction() throws EvaluationException {
        String evaluated = plugin.evaluateValue(null, "unixtime-millis@function", null, null);
        long currentMillis = System.currentTimeMillis();
        long evaluatedMillis = Long.parseLong(evaluated);
        boolean isProper = false;
        long timeLapse = currentMillis - evaluatedMillis;
        // we can accept a minute lapse
        if (timeLapse < 60000 && timeLapse >= 0) {
            isProper = true;
        }
        Assert.assertEquals(isProper, true, "Evaluated time=" + evaluatedMillis + "; Time after method="
                + currentMillis);
    }

    @Test
    public void testEvaluateSimpleMatchesOperator() {
        boolean isTrue = plugin.evaluateOperator(null, "some-string", "matches", "some-string", null, null);
        Assert.assertEquals(isTrue, true);
    }

    @Test
    public void testEvaluateMatchesOperator() {
        boolean isTrue = plugin.evaluateOperator(null, "number-99", "matches", "number-\\d\\d", null, null);
        Assert.assertEquals(isTrue, true);
    }
}
